# _*_coding:utf-8_*_
#04 节
#数据操作

'''
函数：
torch：
torch，arange
torch.reshape
torch.arange(12,dtype=torch.float32).reshape((3,4))
torch.cat((x,y),dim=0/1)
torch.tensor

原生：
x.item()
x.numel()
id(x)



'''
import torch
#张量表示一个数值组成的数组，这个数组可能有多个维度
x = torch.arange(12)  #从0开始生成 12-1 的数
print(x)
# tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
#我们可以通过张量的shape 属性来访问张量的形状和张量中元素的个数
    #要是多维的shape 直接相乘就可以得到 张量里边元素的个数
shape_x = x.shape
print(shape_x)
# torch.Size([12])
numel_x = x.numel()
print(numel_x)
#12     numel : number of element  计算元素的个数  结果永远是一个标量 对于多维数组就比较方便

#要改变一个张量的形状而不改变元素数量和元素值，我们可以调用 reshape 函数
x = x.reshape(3,4)
print(x)
'''
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])
'''

#通过提供包含数值的python列表来为所需张量中的每个元素赋予确定的值
y = torch.tensor([[1,2,3],[2,3,4],[3,4,5]])
print(y)
'''
tensor([[1, 2, 3],
        [2, 3, 4],
        [3, 4, 5]])
'''
y_size = y.shape
print(y_size)
# torch.Size([3, 3])

#常见的标准算束运算符+ - * / ** 都可以升级为暗元素运算
x = torch.tensor([[1.0,2,3,4],[2,3,4,5]])
y = torch.tensor([2,2,2,2])
print(x + y,x - y, x * y,x / y)
'''
tensor([[3., 4., 5., 6.],
        [4., 5., 6., 7.]]) tensor([[-1.,  0.,  1.,  2.],
        [ 0.,  1.,  2.,  3.]]) tensor([[ 2.,  4.,  6.,  8.],
        [ 4.,  6.,  8., 10.]]) tensor([[0.5000, 1.0000, 1.5000, 2.0000],
        [1.0000, 1.5000, 2.0000, 2.5000]]]
        '''
print(x**y) #x ** y  x的y次方
'''
tensor([[ 1.,  4.,  9., 16.],
        [ 4.,  9., 16., 25.]])
'''
#我们也可以把多个张量连结在一起 dimension=0 按列连接 dimension=1 按列连接
x = torch.arange(12,dtype=torch.float32).reshape((3,4))
y = torch.tensor([[1.0,1,1,1],[2.0,2,2,2],[3.0,3,3,3]])
lie = torch.cat((x,y),dim=0)
hang = torch.cat((x,y),dim=1)
print(lie)
print(hang)
'''
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [ 1.,  1.,  1.,  1.],
        [ 2.,  2.,  2.,  2.],
        [ 3.,  3.,  3.,  3.]])
tensor([[ 0.,  1.,  2.,  3.,  1.,  1.,  1.,  1.],
        [ 4.,  5.,  6.,  7.,  2.,  2.,  2.,  2.],
        [ 8.,  9., 10., 11.,  3.,  3.,  3.,  3.]])
'''

#一般来说，形状不同是不能相加的，强行相加就会用到广播机制 来执行按元素操作
a = torch.arange(3).reshape((3,1))
b = torch.arange(2).reshape((1,2))
print(a)
print(b)
'''
tensor([[0],
        [1],
        [2]])
tensor([[0, 1]])
'''
print(a+b)
'''
tensor([[0, 1],
        [1, 2],
        [2, 3]])
'''

#除了读取之外，我们还可以通过指定索引来将元素写入矩阵
print(x)
x[1,1]=1
print(x)
'''
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.]])
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  1.,  6.,  7.],
        [ 8.,  9., 10., 11.]])
'''

#若是书数值的量特别大 我们可以使用原地操作 来减小内存的占用
z = torch.zeros_like(y)
print('id(z):',id(z))
z[:] = x + y
print('id(zz)',id(z))
'''
id(z): 3021400976320
id(zz) 3021400976320         #id() 可以具体查看储存位置
'''           #位置没有变化，所以也就是说明没有创建新的内存

#还可以养成好的习惯 直接 x += y 这样写 就可以节省内存 做个实验
before = id(x)
x += y
a = id(x) == before
print(a)
# True

#tensor 转化为 NumPy 张量
A = x.numpy()
B = torch.tensor(A)
print(type(A),type(B))
# <class 'numpy.ndarray'> <class 'torch.Tensor'>

#将大小为1 的张量转换为Python标量
a = torch.tensor([3.5])
print(a)
print(a.item())
print(float(a))
print(int(a))
'''
tensor([3.5000])
3.5
3.5
3
'''
